package tmt.usercenter.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.tmt.helper.DesHelper;
import com.tmt.sm.impl.ReturnMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import tmt.usercenter.web.Application;
import tmt.usercenter.web.domain.*;
import tmt.usercenter.web.domain.enums.NotifyType;
import tmt.usercenter.web.domain.enums.SystemParamCode;
import tmt.usercenter.web.domain.message.NewUserRole;
import tmt.usercenter.web.domain.security.UserDetailsImpl;
import tmt.usercenter.web.service.*;
import tmt.usercenter.web.vo.HttpResult;
import tmt.usercenter.web.vo.LogoutNotify;
import tmt.usercenter.web.vo.user.ExistUserInfo;
import tmt.usercenter.web.vo.user.RegisterVo;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/external")
public class ExternalController extends BaseController {

    @Autowired
    private LoginHistoryService loginHistoryService;

    @Autowired
    private TmtAuthorityService authorityService;

    @Autowired
    private TmtRoleService roleService;

    @Autowired
    private ClientSystemService clientSystemService;

    @Autowired
    private TmtUserService userService;

    @Autowired
    private UserInfoConfigService uiConfigService;

    @Autowired
    private SmHistoryService smHistoryService;

    @Autowired
    private UserBindingService bindingService;

    @Autowired
    private LoginAttemptService loginAttemptService;


    @ResponseBody()
    @RequestMapping(value = "/logout",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpResult userLogout(HttpServletRequest request, @RequestBody LogoutNotify logoutNotify) {
        try {
            loginHistoryService.userLogout(logoutNotify.getUserId(), logoutNotify.getClientId());
            return HttpResult.success();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return HttpResult.failure();
    }

    /**
     * 用户中心通用通知接口。
     *
     * @param request
     * @param notifyType
     * @param postData
     * @return
     */
    @ResponseBody()
    @PostMapping(value = "/notify/{type}")
    public JSONObject createOrUpdateUser(HttpServletRequest request,
                                         @PathVariable("type") NotifyType notifyType,
                                         @RequestBody(required = false) JSONObject postData) {
        try {
            switch (notifyType) {
                case USER_INTRODUCER_CHANGED:
                    long targetUserId = postData.getLong("targetUserId");
                    long newIntroducerId = postData.getLong("newIntroducerId");
                    userService.changeIntroducer(targetUserId, newIntroducerId);
                    break;
                default:
                    break;
            }
            return HttpResult.success().toJSONObject();
        } catch (Exception ex) {
            ex.printStackTrace();
            return HttpResult.failure("执行失败：" + ex.getMessage()).toJSONObject();
        }
    }


    @ResponseBody()
    @GetMapping(value = "/user/lock/release/{userId}")
    public HttpResult releaseLockedUser(@PathVariable long userId) {
        try {
            TmtUser tmtUser = userService.findById(userId);
            loginAttemptService.loginSucceeded(tmtUser.getUsername());
            return HttpResult.success("解锁用户成功");
        } catch (Exception ex) {
            return HttpResult.failure("解锁用户失败：" + ex.getMessage());
        }
    }

    /**
     * 外部系统用户导入方法
     *
     * @param request
     * @param registerVo
     * @return
     */
    @ResponseBody()
    @RequestMapping(value = "/register/member",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpResult batchImportUser(HttpServletRequest request, @RequestBody RegisterVo registerVo) {
        try {
            try {
                String authorization = request.getHeader("Authorization");
                List<String> securityInfos = Arrays.stream(authorization.split(" "))
                        .filter(x -> x.trim().length() > 0).collect(Collectors.toList());
                String username = securityInfos.get(0);
                String password = securityInfos.get(1);
                //先解密
                password = DesHelper.decrypt(password);
                if (!userService.existsByUsernameAndPassword(username, password))
                    throw new Exception();
            } catch (Exception ex) {
                throw new Exception("未授权的请求");
            }

            //检查对象属性值是否有效
            BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(registerVo, "registerVo");
            //rgValidator.validate(registerVo, bindingResult);

            if (StringUtils.isEmpty(registerVo.getClientId())) {
                throw new Exception("用户数据clientId字段不能为空");
            }

            UserInfoConfig config = uiConfigService.findByOriginSystemClientId(registerVo.getClientId(), true);
            if (config == null) {
                throw new Exception("用户数据clientId字段的值无效");
            }

            //如果存在配置的必填字段错误，则返回填写页面。
            if (bindingResult.hasErrors()
                    && bindingResult.getAllErrors().stream().anyMatch(x -> config.getRequiredInfo().contains(((FieldError) x).getField()))) {
                return HttpResult.failure("用户数据校验失败", bindingResult.getAllErrors());
            }

            //初始化用户对象
            String host = request.getRequestURL().toString().split(request.getRequestURI())[0];
            String defaultAvatar = TmtFileUrlFieldConverter.getDefaultFileUrl(host, TmtUser.class, "avatar");
            TmtUser user = registerVo.convertToUser(defaultAvatar, UUID.randomUUID().toString(), RegisterController.DEFAULT_PASSWORD);

            TmtUser curUser = userService.findByUsername(user.getUsername());
            if (curUser != null) {
                return HttpResult.success("注册成功", curUser.getId());
            }

            ClientSystem originSystem = clientSystemService.findByClientId(registerVo.getClientId());
            user.setOriginSystem(originSystem);

            //设置用户角色
            List<TmtUserRole> roleList = new ArrayList<>();
            user.setUserRoles(roleList);

            ClientSystem system = clientSystemService.findByClientId(Application.SYSTEM_ID);
            TmtRole role = roleService.findDefaultRoleByOriginSystemId(system.getId());
            if (role != null)
                roleList.add(new TmtUserRole(user, role));

            if (!Objects.equals(originSystem.getId(), system.getId())) {
                TmtRole role1 = roleService.findDefaultRoleByOriginSystemId(originSystem.getId());
                roleList.add(new TmtUserRole(user, role1));
            }

            if (!StringUtils.isEmpty(registerVo.getDefaultRoles())) {
                Arrays.stream(registerVo.getDefaultRoles().split(",")).forEach(x -> {
                    String roleCode = x.trim();
                    if (StringUtils.isEmpty(roleCode))
                        return;

                    if (roleList.stream().anyMatch(y -> Objects.equals(y.getRole().getCode(), roleCode)))
                        return;

                    TmtRole tmpRole = roleService.findByCodeAndClientId(roleCode, registerVo.getClientId());
                    if (tmpRole != null) {
                        roleList.add(new TmtUserRole(user, tmpRole));
                    }
                });
            }

            //保存用户对象
            userService.registerNewUser(user);

            //throw new Exception("测试");

            return HttpResult.success("注册成功", user.getId());
        } catch (Exception ex) {
            return HttpResult.failure(ex.getMessage());
        }
    }

    @ResponseBody()
    @RequestMapping(value = "/register/authority",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpResult createClientAuthority(HttpServletRequest request, @RequestBody List<TmtAuthority> tmtAuthorities) {
        try {
            authorityService.updateAuthorities(tmtAuthorities);
            return HttpResult.success();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return HttpResult.failure();
    }

    @ResponseBody()
    @RequestMapping(value = "/register/role",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpResult createClientRole(HttpServletRequest request, @RequestBody List<TmtRole> tmtRoles) {
        try {
            roleService.updateRoles(tmtRoles);
            return HttpResult.success();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return HttpResult.failure();
    }

    @ResponseBody()
    @RequestMapping(value = "/role/update",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpResult changeUserRole(HttpServletRequest request, @RequestBody NewUserRole newUserRole) {
        try {
            if (newUserRole.getAction() < 0) {
                roleService.deleteBy(newUserRole);
            } else if (newUserRole.getAction() > 0) {
                roleService.createBy(newUserRole);
            } else {
                //同步；
                roleService.updateBy(newUserRole);
            }

            UserDetailsImpl details = userService.getUserDetailsImpl(newUserRole.getUserId(), newUserRole.getClientId());
            return HttpResult.success("执行成功", details);
        } catch (Exception ex) {
            logger.error("-------------ExternalController.changeUserRole--------------" + ex.getMessage());
        }
        return HttpResult.failure();
    }

    @ResponseBody()
    @RequestMapping(value = "/sm",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpResult sendSm(HttpServletRequest request, @RequestBody SmHistory smHistory) {
        try {
            smHistoryService.sendSm(smHistory.getOriginSystem().getClientId(), smHistory.getToMobile(), smHistory.getContent(),
                    smHistory.getFuncPoint(), true, ReturnMode.SYNC_MODE);
            return HttpResult.success();
        } catch (Exception ex) {
            logger.error("-------------ExternalController.sendSm--------------" + ex.getMessage());
        }
        return HttpResult.failure();
    }


    @ResponseBody()
    @RequestMapping(value = "/openid/query",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpResult queryTmtUserIdByOpenId(HttpServletRequest request,
                                             @RequestBody UserBinding openIdInfo) {
        try {
            UserBinding userBinding = bindingService.findByOpenIdAndBindingType(openIdInfo.getOpenId(), openIdInfo.getBindingType());
            return userBinding != null ? HttpResult.success("操作成功", userBinding.getUser().getId())
                    : HttpResult.failure("用户不存在");
        } catch (Exception ex) {
            logger.error("-------------ExternalController.queryTmtUserIdByOpenId--------------" + ex.getMessage());
        }
        return HttpResult.failure();
    }

    @ResponseBody()
    @RequestMapping(value = "/openid/update",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpResult UpdateOpenId(HttpServletRequest request,
                                   @RequestBody UserBinding openIdInfo) {
        String errMsg = null;
        try {
            bindingService.updateOpenId(openIdInfo);
            return HttpResult.success("操作成功", openIdInfo.getUser().getId());
        } catch (Exception ex) {
            errMsg = ex.getMessage();
        }
        return HttpResult.failure(errMsg);
    }

    @ResponseBody()
    @RequestMapping(value = "/exist/user",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpResult existsUser(HttpServletRequest request,
                                 @RequestBody ExistUserInfo existUserInfo) {
        String errMsg = null;
        try {
            if (userService.existsBy(existUserInfo)) {
                return HttpResult.success("操作成功");
            } else {
                return HttpResult.failure("用户信息不匹配");
            }
        } catch (Exception ex) {
            errMsg = ex.getMessage();
        }
        return HttpResult.failure(errMsg);
    }

    @ResponseBody()
    @RequestMapping(value = "/user/delete/{id}",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpResult deleteUser(HttpServletRequest request, @PathVariable long id) {
        String errMsg = null;
        try {
            userService.delete(new TmtUser(id));
            return HttpResult.success();
        } catch (Exception ex) {
            errMsg = ex.getMessage();
        }
        return HttpResult.failure("操作失败：" + errMsg);
    }
}
